home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 June / MacFormat 25.iso / Shareware City / Developers / ICAppSourceKit1.0 / ICTextWhats.p < prev    next >
Encoding:
Text File  |  1994-11-11  |  12.2 KB  |  449 lines  |  [TEXT/PJMM]

  1. unit ICTextWhats;
  2.  
  3. interface
  4.  
  5.     uses
  6.         ICWindowGlobals;
  7.  
  8.     function WhatOpenText (wt: WindowType; item: integer): OSErr;
  9.     function WhatFlushText (wt: WindowType; item: integer): OSErr;
  10.     function WhatCloseText (wt: WindowType; item: integer): OSErr;
  11.     function WhatClickText (wt: WindowType; item: integer; er: eventRecord): OSErr;
  12.     function WhatKeyText (wt: WindowType; item: integer; er: EventRecord): OSErr;
  13.  
  14.     (* danger, layer break! *)
  15.     function HaveTextSelection (wt: WindowType): boolean;
  16.     procedure AdjustTextMenu (wt: WindowType);
  17.     procedure DoTextMenu (wt: WindowType; menuitem: integer);
  18.     procedure SelectTextItem (wt: WindowType; item: integer);
  19.  
  20. implementation
  21.  
  22.     uses
  23.         ICTypes, ICAPI, 
  24.  
  25.         ICGlobals, ICMiscSubs, ICSubs, ICText, ICDialogs, ICDocUtils;
  26.  
  27.     const
  28.         tf_single_line = 0;
  29.         tf_pstring = 1;
  30.         tf_scrambled = 2;
  31.         tf_monospace = 3;
  32.  
  33.         tf_single_line_mask = $0001;
  34.         tf_pstring_mask = $0002;
  35.         tf_scrambled_mask = $0004;
  36.         tf_monospace_mask = $0008;
  37.  
  38.     procedure DrawTextProc (window: DialogPtr; item: integer);
  39.         var
  40.             r: Rect;
  41.             savefont, savemode, savesize: integer;
  42.             saveface: Style;
  43.     begin
  44.         savefont := window^.txFont;
  45.         saveface := window^.txFace;
  46.         savemode := window^.txMode;
  47.         savesize := window^.txSize;
  48.         TextDraw(windowinfo[GetWindowType(window)].items[item]^.data);
  49.  
  50.         GetDItemRect(window, item, r);
  51.         InsetRect(r, -3, -3);
  52.         PenNormal;
  53.         FrameRect(r);
  54.         TextFont(savefont);
  55.         TextFace(saveface);
  56.         TextMode(savemode);
  57.         TextSize(savesize);
  58.     end;
  59.  
  60.     function HaveTextSelection (wt: WindowType): boolean;
  61.         var
  62.             start_sel, end_sel: integer;
  63.     begin
  64.         HaveTextSelection := false;
  65.         if GetSelectedItem(wt) > 0 then begin
  66.             TextGetSelect(windowinfo[wt].items[GetSelectedItem(wt)]^.data, start_sel, end_sel);
  67.             HaveTextSelection := (start_sel <> end_sel);
  68.         end; (* if *)
  69.     end; (* HaveTextSelection *)
  70.  
  71.     procedure AdjustTextMenu (wt: WindowType);
  72.         var
  73.             enable_cut, enable_paste, enable_select_all: boolean;
  74.             offset: longint;
  75.             mh: MenuHandle;
  76.             texth: Handle;
  77.             text_size: longint;
  78.             search_text: integer;
  79.             cr_pos: longint;
  80.             item: integer;
  81.             err: OSErr;
  82.             sel_start, sel_end: integer;
  83.     begin
  84.         item := GetSelectedItem(wt);
  85.         if (wt <> WT_None) & (item > 0) then begin
  86.             enable_cut := HaveTextSelection(wt);
  87.             offset := 0;
  88.             enable_paste := (GetScrap(nil, 'TEXT', offset) > 0);
  89.             TextGetSelect(windowinfo[wt].items[item]^.data, sel_start, sel_end);
  90.             TextGetSize(windowinfo[wt].items[item]^.data, text_size);
  91.             enable_select_all := (sel_start <> 0) or (sel_end <> text_size);
  92.         end
  93.         else begin
  94.             enable_cut := false;
  95.             enable_paste := false;
  96.             enable_select_all := false;
  97.         end; (* if *)
  98.         (* deal with the nasty paste problem, ie preventing them pasting CRs into single line fields *)
  99.         if enable_paste & btst(windowinfo[wt].items[item]^.flags, tf_single_line) then begin
  100.             texth := NewHandle(0);
  101.             err := MemError;
  102.             if err = noErr then begin
  103.                 offset := 0;
  104.                 text_size := GetScrap(texth, 'TEXT', offset);
  105.                 if text_size > 0 then begin
  106.                     search_text := $0D0D;
  107.                     cr_pos := Munger(texth, 0, @search_Text, 1, nil, 0);
  108.                     if cr_pos < 0 then begin
  109.                         enable_paste := true;
  110.                     end
  111.                     else if (cr_pos = text_size - 1) then begin
  112.                         enable_paste := (cr_pos > 0);
  113.                     end
  114.                     else begin
  115.                         enable_paste := false;
  116.                     end; (* if *)
  117.                 end
  118.                 else begin
  119.                     enable_paste := false;
  120.                 end; (* if *)
  121.             end; (* if *)
  122.             if texth <> nil then begin
  123.                 DisposeHandle(texth);
  124.             end; (* if *)
  125.             if err <> noErr then begin
  126.                 enable_paste := false;
  127.             end; (* if *)
  128.         end; (* if *)
  129.         (* deal with locked items *)
  130.         if item > 0 then begin
  131.             if IsLocked(wt, item) then begin
  132.                 enable_paste := false;
  133.                 enable_cut := false;
  134.             end; (* if *)
  135.         end; (* if *)
  136.         (* hit the menu items *)
  137.         mh := GetMHandle(M_Edit);
  138.         SetItemEnable(mh, EM_Undo, false);
  139.         SetItemEnable(mh, EM_Cut, enable_cut);
  140.         SetItemEnable(mh, EM_Copy, enable_cut);
  141.         SetItemEnable(mh, EM_Paste, enable_paste);
  142.         SetItemEnable(mh, EM_Clear, enable_cut);
  143.         SetItemEnable(mh, EM_SelectAll, enable_select_all);
  144.     end;
  145.  
  146.     procedure SelectTextItem (wt: WindowType; item: integer);
  147.     begin
  148.         if GetSelectedItem(wt) > 0 then begin
  149.             TextActivate(windowinfo[wt].items[GetSelectedItem(wt)]^.data, false);
  150.         end;
  151.         TextActivate(windowinfo[wt].items[item]^.data, true);
  152.         windowinfo[wt].selected_item := item;
  153.     end; (* SelectTextItem *)
  154.  
  155.     procedure DoTextMenu (wt: WindowType; menuitem: integer);
  156.         var
  157.             data: Ptr;
  158.             texth: Handle;
  159.             offset: longint;
  160.             search_text: integer;
  161.             cr_pos: longint;
  162.             item: integer;
  163.             text_size: longint;
  164.     begin
  165.         item := GetSelectedItem(wt);
  166.         data := windowinfo[wt].items[item]^.data;
  167.         case menuitem of
  168.             EM_Cut:  begin
  169.                 TextCut(data);
  170.             end;
  171.             EM_Copy:  begin
  172.                 TextCopy(data);
  173.             end;
  174.             EM_Paste: 
  175.                 if IsLocked(wt, item) then begin
  176.                     LockedAlert(wt, item);
  177.                 end
  178.                 else begin
  179.                     if btst(windowinfo[wt].items[item]^.flags, tf_single_line) then begin
  180.                         texth := NewHandle(0);
  181.                         if texth <> nil then begin
  182.                             offset := 0;
  183.                             text_size := GetScrap(texth, 'TEXT', offset);
  184.                             if text_size > 0 then begin
  185.                                 search_text := $0D0D;
  186.                                 cr_pos := Munger(texth, 0, @search_Text, 1, nil, 0);
  187.                                 if cr_pos > 0 then begin
  188.                                     SetHandleSize(texth, cr_pos);
  189.                                 end; (* if *)
  190.                                 TextClear(data);
  191.                                 TextInsert(data, texth);
  192.                             end; (* if *)
  193.                         end; (* if *)
  194.                         DisposeHandle(texth);
  195.                     end
  196.                     else begin
  197.                         TextPaste(data);
  198.                     end; (* if *)
  199.                 end; (* if *)
  200.             EM_Clear:  begin
  201.                 if IsLocked(wt, item) then begin
  202.                     LockedAlert(wt, item);
  203.                 end
  204.                 else begin
  205.                     TextClear(data);
  206.                 end; (* if *)
  207.             end;
  208.             EM_SelectAll:  begin
  209.                 TextSetSelect(data, 0, 32767);
  210.             end;
  211.             otherwise
  212.                 ;
  213.         end; (* case *)
  214.     end; (* DoTextMenu *)
  215.  
  216.     type
  217.         memBlock = packed array[0..16000000] of byte;
  218.         memBlockPtr = ^memBlock;
  219.  
  220.     function BlockCompare (lhs, rhs: univ Ptr; size: longint): boolean;
  221.         var
  222.             i: longint;
  223.             tmplhs, tmprhs: memBlockPtr;
  224.     begin
  225.         BlockCompare := false;
  226.         tmplhs := memBlockPtr(lhs);
  227.         tmprhs := memBlockPtr(rhs);
  228.         for i := 0 to size - 1 do begin
  229.             if tmplhs^[i] <> tmprhs^[i] then begin
  230.                 exit(BlockCompare);
  231.             end; (* if *)
  232.         end; (* for *)
  233.         BlockCompare := true;
  234.     end; (* BlockCompare *)
  235.  
  236.     procedure ScrambleHandle (texth: Handle);
  237.         var
  238.             l: longint;
  239.             tmptext: memBlockPtr;
  240.     begin
  241.         tmptext := memBlockPtr(texth^);
  242.         for l := 1 to GetHandleSize(texth) do begin
  243.             tmptext^[l - 1] := band(bxor(tmptext^[l - 1], $55 + l), $FF);
  244.         end; (* for *)
  245.     end; (* ScrambleHandle *)
  246.  
  247. {$PUSH}
  248. {$R-}
  249.     procedure BlockFill (p: univ ptr; len: longInt; value: integer);
  250.     begin
  251.         while (len > 0) do begin
  252.             p^ := value;
  253.             len := len - 1;
  254.             longInt(p) := longInt(p) + 1;
  255.         end;
  256.     end;
  257. {$POP}
  258.  
  259.     function WhatOpenText (wt: WindowType; item: integer): OSErr;
  260.         var
  261.             err: OSErr;
  262.             key: Str31;
  263.             attr: longint;
  264.             texth: Handle;
  265.             textsize: longint;
  266.             junk: longint;
  267.             flags: longint;
  268.             pstring: boolean;
  269.             scrambled: boolean;
  270.             font, size: integer;
  271.             r: Rect;
  272.     begin
  273.         windowinfo[wt].items[item]^.data := nil;
  274.         windowinfo[wt].items[item]^.spare_data := nil;
  275.         texth := nil;
  276.         key := windowinfo[wt].items[item]^.key;
  277.         flags := windowinfo[wt].items[item]^.flags;
  278.         pstring := btst(flags, tf_pstring);
  279.         scrambled := btst(flags, tf_scrambled);
  280.         if btst(flags, tf_monospace) then begin
  281.             font := monaco;
  282.             size := 9;
  283.         end
  284.         else begin
  285.             font := systemFont;
  286.             size := 12;
  287.         end; (* if *)
  288.         err := ICMapErr(ICGetPrefHandle(GetInstance, key, attr, texth));
  289.         if err = noErr then begin
  290.             ProcessAttributes(wt, item, attr);
  291.             if pstring then begin
  292.                 junk := Munger(texth, 0, nil, 1, @junk, 0);
  293.             end; (* if *)
  294.             if scrambled then begin
  295.                 ScrambleHandle(texth);
  296.             end; (* if *)
  297.             err := TextCreate(windowinfo[wt].items[item]^.data, windowinfo[wt].window, item, font, size, IsLocked(wt, item));
  298.         end; (* if *)
  299.         if err = noErr then begin
  300.             SetDItemHandle(windowinfo[wt].window, item, @DrawTextProc);
  301.             TextInsert(windowinfo[wt].items[item]^.data, texth);
  302.         end; (* if *)
  303.         if (err = noErr) & scrambled then begin
  304.             windowinfo[wt].items[item]^.spare_data := windowinfo[wt].items[item]^.data;
  305.             windowinfo[wt].items[item]^.data := nil;
  306.             GetDItemRect(windowinfo[wt].window, item, r);
  307.             OffsetRect(r, 16000, 0);
  308.             TextMove(windowinfo[wt].items[item]^.spare_data, r);
  309.             BlockFill(texth^, GetHandleSize(texth), ord('•'));
  310.             err := TextCreate(windowinfo[wt].items[item]^.data, windowinfo[wt].window, item, font, size, IsLocked(wt, item));
  311.             if err = noErr then begin
  312.                 TextInsert(windowinfo[wt].items[item]^.data, texth);
  313.             end; (* if *)
  314.         end; (* if *)
  315.         if texth <> nil then begin
  316.             DisposeHandle(texth);
  317.         end; (* if *)
  318.         WhatOpenText := err;
  319.     end; (* WhatOpenText *)
  320.  
  321. (* *)
  322.  
  323.     function WhatFlushText (wt: WindowType; item: integer): OSErr;
  324.         var
  325.             err: OSErr;
  326.             key: Str31;
  327.             texth: Handle;
  328.             oldtexth: Handle;
  329.             attr: longint;
  330.             junk: longint;
  331.             i: integer;
  332.             flags: longint;
  333.             pstring: boolean;
  334.             scrambled: boolean;
  335.     begin
  336.         texth := nil;
  337.         oldtexth := nil;
  338.         key := windowinfo[wt].items[item]^.key;
  339.         flags := windowinfo[wt].items[item]^.flags;
  340.         pstring := btst(flags, tf_pstring);
  341.         scrambled := btst(flags, tf_scrambled);
  342.         err := ICMapErr(ICGetPrefHandle(GetInstance, key, attr, oldtexth));
  343.         if err = noErr then begin
  344.             if pstring and (GetHandleSize(oldtexth) = 0) then begin
  345.                 SetHandleSize(oldtexth, 1);
  346.                 err := MemError;
  347.                 if err = noErr then begin
  348.                     oldtexth^^ := 0;
  349.                 end; (* if *)
  350.             end; (* if *)
  351.         end; (* if *)
  352.         if err = noErr then begin
  353.             texth := NewHandle(0);
  354.             err := MemError;
  355.         end; (* if *)
  356.         if err = noErr then begin
  357.             if scrambled then begin
  358.                 TextGet(windowinfo[wt].items[item]^.spare_data, texth);
  359.             end
  360.             else begin
  361.                 TextGet(windowinfo[wt].items[item]^.data, texth);
  362.             end; (* if *)
  363.             if scrambled then begin
  364.                 ScrambleHandle(texth);
  365.             end; (* if *)
  366.             if pstring then begin
  367.                 if GetHandleSize(texth) > 255 then begin
  368.                     SetHandleSize(texth, 255);
  369.                 end; (* if *)
  370.                 i := GetHandleSize(texth) * $0101;                    (* puts it into both bytes! *)
  371.                 junk := Munger(texth, 0, nil, 0, @i, 1);            (* if this errors, we lose *)
  372.             end; (* if *)
  373.             if not IsLocked(wt, item) & ((GetHandleSize(texth) <> GetHandleSize(oldtexth)) | not BlockCompare(texth^, oldtexth^, GetHandleSize(texth))) then begin
  374.                 err := ICMapErr(ICSetPrefHandle(GetInstance, key, ICattr_no_change, texth));
  375.                 if err = noErr then begin
  376.                     DirtyDocument;
  377.                 end; (* if *)
  378.             end; (* if *)
  379.         end; (* if *)
  380.         if texth <> nil then begin
  381.             DisposeHandle(texth);
  382.         end; (* if *)
  383.         if oldtexth <> nil then begin
  384.             DisposeHandle(oldtexth);
  385.         end; (* if *)
  386.         WhatFlushText := err;
  387.     end; (* WhatFlushText *)
  388.  
  389. (* *)
  390.  
  391.     function WhatCloseText (wt: WindowType; item: integer): OSErr;
  392.         var
  393.             flags: longint;
  394.             scrambled: boolean;
  395.     begin
  396.         flags := windowinfo[wt].items[item]^.flags;
  397.         scrambled := btst(flags, tf_scrambled);
  398.         TextDestroy(windowinfo[wt].items[item]^.data);
  399.         if scrambled then begin
  400.             TextDestroy(windowinfo[wt].items[item]^.spare_data);
  401.         end; (* if *)
  402.         WhatCloseText := noErr;
  403.     end; (* WhatCloseText *)
  404.  
  405. (* *)
  406.  
  407.     function WhatClickText (wt: WindowType; item: integer; er: eventRecord): OSErr;
  408.     begin
  409.         SelectTextItem(wt, item);
  410.         TextClick(windowinfo[wt].items[item]^.data, er);
  411.         WhatClickText := noErr;
  412.     end; (* WhatClickText *)
  413.  
  414.     function WhatKeyText (wt: WindowType; item: integer; er: EventRecord): OSErr;
  415.         var
  416.             flags: longint;
  417.             scrambled: boolean;
  418.             ch: char;
  419.             sel_start, sel_end: integer;
  420.     begin
  421.         flags := windowinfo[wt].items[item]^.flags;
  422.         scrambled := btst(flags, tf_scrambled);
  423.         ch := chr(BAND(er.message, charCodeMask));
  424.         if (btst(flags, tf_single_line) and (ch = chr(13))) or (scrambled and ((ch <> chr(8)) and (ch < ' '))) then begin
  425.             SysBeep(1);
  426.         end
  427.         else begin
  428.             if IsLocked(wt, item) and DirtyKey(ch) then begin
  429.                 LockedAlert(wt, item);
  430.             end
  431.             else begin
  432.                 if scrambled then begin
  433.                     TextGetSelect(windowinfo[wt].items[item]^.data, sel_start, sel_end);
  434.                     TextSetSelect(windowinfo[wt].items[item]^.spare_data, sel_start, sel_end);
  435.                     TextKey(windowinfo[wt].items[item]^.spare_data, er);
  436.                     if (ch <> chr(8)) & DirtyKey(ch) then begin
  437.                         er.message := ord('•');
  438.                     end;
  439.                     TextKey(windowinfo[wt].items[item]^.data, er);
  440.                 end
  441.                 else begin
  442.                     TextKey(windowinfo[wt].items[item]^.data, er);
  443.                 end; (* if *)
  444.             end; (* if *)
  445.         end; (* if *)
  446.         WhatKeyText := noErr;
  447.     end; (* WhatKeyText *)
  448.  
  449. end. (* TextWhats *)